package com.ai.modbus;

import cn.hutool.core.util.ObjectUtil;
import com.ai.common.CommonResponse;
import com.serotonin.modbus4j.ModbusMaster;
import com.serotonin.modbus4j.code.DataType;
import com.serotonin.modbus4j.exception.ErrorResponseException;
import com.serotonin.modbus4j.exception.ModbusInitException;
import com.serotonin.modbus4j.exception.ModbusTransportException;
import com.serotonin.modbus4j.ip.IpParameters;
import com.serotonin.modbus4j.locator.BaseLocator;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

/**
 * @Author jiaok
 * @Date 2024-11-25 16:02
 */
@Component
@Slf4j
public class ModbusProvide {

    @Value("${modbus.ip}")
    private  String modbusIp ;

    @Value("${modbus.port}")
    private  Integer modbusPort ;


    /**
     * 获取modbusTcp的客户端连接
     * @param host ip
     * @param port 端口 默认为502
     * @return 创建modbus-tcp通信客户端连接
     * @throws ModbusInitException 创建失败
     */
    public static ModbusMaster getMasterTcp(String host, Integer port) throws ModbusInitException {

        IpParameters ipParameters = new IpParameters();
        ipParameters.setHost(host);
        ipParameters.setPort(port);

        //创建modbus-tcp通信客户端连接
        ModbusMaster tcpMaster = ModbusFactoryProvide.getModbusFactory().createTcpMaster(ipParameters, true);
        tcpMaster.init();
        return tcpMaster;
    }


    /**
     * 读取指定寄存器存储的值
     * @param slaveId  从机id
     * @param offset 偏移量，默认从40001开始， （若读取40003，则需设为40003-40001=2）
     * @param dataType 存储值的数据类型
     * @return 值
     * @throws ModbusTransportException
     * @throws ErrorResponseException
     */
    public static Number readHoldingRegister(ModbusMaster modbusMaster,int slaveId, int offset, int dataType)
            throws ModbusTransportException, ErrorResponseException {
        BaseLocator<Number> loc = BaseLocator.holdingRegister(slaveId, offset, dataType);
        Number value = modbusMaster.getValue(loc);
        return value;
    }

    public CommonResponse getNodeValue(Integer offset ,Integer slave) {
        IpParameters ipParameters = new IpParameters();

        ipParameters.setHost(modbusIp);
        ipParameters.setPort(modbusPort);

        //创建modbus-tcp通信客户端连接
        ModbusMaster tcpMaster = ModbusFactoryProvide.getModbusFactory().createTcpMaster(ipParameters, true);
        try {
            tcpMaster.init();
            log.info("===========================     开始读取节点值      ===========================");
            Number number = readHoldingRegister(tcpMaster, slave, offset, DataType.TWO_BYTE_INT_UNSIGNED);
            log.info("===========================      值：{}       ===========================",number);
            return CommonResponse.ok(number);
        }  catch (ModbusInitException e) {
            log.error("Modbus TCP连接建立失败: {}", e.getMessage());
            throw new RuntimeException("Modbus连接失败，检查设备或网络配置", e);
         } catch (ModbusTransportException e) {
             log.error("Modbus Transport Error: {}", e.getMessage());
             throw new RuntimeException("Modbus传输错误，请检查请求和网络", e);
         } catch (ErrorResponseException e) {
             log.error("Modbus从机返回错误响应: {}", e.getErrorResponse());
             throw new RuntimeException("Modbus响应错误，请检查从机配置", e);
         }finally {
                 // 释放资源
            tcpMaster.destroy();
            log.info("Modbus连接已关闭");
        }
    }
}
